/*
 * SvrClient.cpp
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */
#include "SvrClient.h"

SvrClient::SvrClient(void)
{
    count = 0;
    client_time_tick = 0;
    this->pSvrconfig = NULL;
    this->pSvrtask = NULL;
    this->pSvrlog = NULL;
    this->pDbutils = NULL;
}

SvrClient::~SvrClient(void)
{
    /*add your code here*/
}

/*
 * init server client
 */
int SvrClient::init(SvrConfig * pconfig,SvrTask * psvrtask,Svr_log * psvrlog,DbAccess * pdbaccess,SvrFileManage * psvrfilemanage,int init_size)
{
    if(pconfig == NULL
    		||psvrtask == NULL
    		||psvrlog == NULL
    		||pdbaccess == NULL)
        return FAILURE;

    this->pSvrconfig = pconfig;
    this->pSvrtask = psvrtask;
    this->pSvrlog = psvrlog;
    this->pDbutils = pdbaccess;
    this->pSvrFileUtils = psvrfilemanage;

    /*
    *alloc client token
    */
    for(int i = 0 ;i < init_size;i++)
    {
        user_token * token = NULL;
        token = new user_token();
        if(token != NULL)
        {
            client_pool.push(token);
            count++;
        }
    }

    return SUCCESS;
}

/*
*token pool operation
*/
void SvrClient::alloc(user_token ** client)
{
    pool_lock.Lock();
    {
        if(client_pool.size() >0 )
        {
             *client = client_pool.top();
             client_pool.pop();
        }
        else
        {
             *client = new user_token();
             count++;
        }
        /*init*/
        (*client)->tConnTime = time(NULL);
        (*client)->timeConnBegin = time(NULL);
        /*end*/
        pool_lock.Unlock();
    }
}

void SvrClient::free(user_token * client)
{
    pool_lock.Lock();
    {
        if(client != NULL)
        {
              client->id = 0;
              client->type = 0;
              client->index = 0;
              memset(client->key,'\0',sizeof(client->key));

              client->offset = 0;
              client->length = 0;
              client->count = 0;
              client->trans_size = 0;
              client->have_trans_size = 0;
              client->last_size = 0;

              if(client->filefd >= 0)
              {
                  close(client->filefd);
                  client->filefd = -1;
              }
              client->hFile_size = 0;
              client->hFile_offset = 0;

              client->send_timeout = 0;
              client->receive_timeout = 0;
              client->trans_file_timeout = 0;
              client->tConnTime = time(NULL);
              client->timeConnBegin = time(NULL);
              client->connectionFlag = 0;
              client->recv_send_flag = FALSE;
              client->conn_index = 0;
              client->privt = NULL;

              client_pool.push(client);
        }
        pool_lock.Unlock();
    }
}

int SvrClient::get_free_count()
{
    return (int)client_pool.size();
}

int SvrClient::get_count()
{
     return count;
}

/*
*alloc_request_header
*/
void SvrClient::alloc_request_header(http_request_header ** hrt)
{
    http_lock.Lock();
    {
        if(this->http_request_header_pool.size()>0)
        {
            *hrt = http_request_header_pool.top();
            http_request_header_pool.pop();
        }
        else
        {
            (*hrt) = new http_request_header();
        }
        http_lock.Unlock();
    }
}

/*
*free_request_header
*/
void SvrClient::free_request_header(http_request_header * hrt)
{
    http_lock.Lock();
    {
        if(hrt != NULL)
        {
            http_request_header_pool.push(hrt);
        }
        http_lock.Unlock();
    }
}

/*
*op buf alloc and free
*/
void SvrClient::alloc_op_buf(op_buf ** pbf)
{
    op_buf_lock.Lock();
    {
          if(this->op_buf_pool.size() > 0)
          {
              *pbf = op_buf_pool.top();
              op_buf_pool.pop();
          }
          else
          {
              *pbf = new op_buf();
              (*pbf)->buf = new ubyte[op_buf_len];
              (*pbf)->len = op_buf_len;
              memset((*pbf)->buf,'\0',op_buf_len);
          }
          op_buf_lock.Unlock();
    }
}

/*
*op buf alloc and free
*/
void SvrClient::free_op_buf(op_buf * pbf)
{
    op_buf_lock.Lock();
    {
        if(pbf != NULL)
        {
            memset(pbf->buf,'\0',op_buf_len);
            op_buf_pool.push(pbf);
        }
        op_buf_lock.Unlock();
    }
}

/*
*open request file
*/
bool SvrClient::open_request_file(http_request_header * hrt,user_token * token)
{
    if(strlen(this->pSvrconfig->rootpath) == 0 || hrt->file_name_len < 1)
    {
        pSvrlog->log_fmt(LOG_ERR,"root path or file_name is null");
        return false;
    }

    int retvalue  = false;
    /*transmit file name codes*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        pSvrlog->log_fmt(LOG_ERR,"alloc op buf failure,open_request_file");
        return false;
    }

    /*get virtual path name */
	char * fptr = NULL;
	fptr = strstr(hrt->file_name + 1,"/");
	if(fptr != NULL)
	{
		m_src_code->len = fptr - hrt->file_name - 1;
		if(m_src_code->len > 0)
		{
			memcpy(m_src_code->buf,hrt->file_name + 1,m_src_code->len);
		}
	}
	/*get virtual direction*/
	bool ret = this->pSvrFileUtils->get_vir_dir((char *)m_src_code->buf,(char *)m_dest_code->buf,op_buf_len);
	/*get file name*/
	if(ret)
	{
		strcat((char *)m_dest_code->buf,fptr);
	}
	else
	{
		strcat((char *)m_dest_code->buf,hrt->file_name);
	}

    /*replace '\\' to '/' */
    size_t index = 0;
    size_t len = strlen((char *)m_dest_code->buf);
    while(index < len)
    {
        if((*(m_dest_code->buf+index)) == '\\')
                (*(m_dest_code->buf+index)) = '/';
        /*next char*/
        index++;
    }
    pSvrlog->log_fmt(LOG_INFO,"open file :%s\r\n",(char *)m_dest_code->buf);
    /*
    *open Linux file fd
    */
    token->filefd = this->pSvrFileUtils->open_file((char *)m_dest_code->buf,token->hFile_size);
    if(token->filefd >= 0 && token->hFile_size > 0)
    {
    	 retvalue = true;
    }

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    return retvalue;
}

/*
*decode file name
*/
bool SvrClient::decode_file_name(http_request_header * hrt,user_token * token)
{
    if(hrt == NULL || token == NULL)
         return false;

    /*begin check ,valid ,decode the filename*/
    unsigned int index = 0;
    char * pChar = _NULL;
    /*check is can decode*/
    pChar = strrchr(hrt->file_name,'.');
    if(pChar != NULL)
    {
        return false;
    }

    /*replace struct char to base64 char*/
    while(index <hrt->file_name_len)
    {
        if((*(hrt->file_name+index)) == '-')
                (*(hrt->file_name+index)) = '=';
        if((*(hrt->file_name+index)) == '^')
                (*(hrt->file_name+index)) = '/';
        if((*(hrt->file_name+index)) == '~')
                (*(hrt->file_name+index)) = '/';
        /*next char*/
        index++;
    }
    /*
    *now begin base64 decode
    */
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*copy file name*/
    memcpy(m_src_code->buf,hrt->file_name,hrt->file_name_len);
    m_src_code->len = hrt->file_name_len;
    size_t ret_len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);
    m_dest_code->len = ret_len;

    /*now begin url decode twice*/
    memset(m_src_code->buf,'\0',op_buf_len);
    m_src_code->len = 0;
    m_src_code->len = utils::url_decode(m_src_code->buf,op_buf_len,m_dest_code->buf,m_dest_code->len);

    memset(m_dest_code->buf,'\0',op_buf_len);
    m_dest_code->len = 0;
    m_dest_code->len = utils::url_decode(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);

    /*copy decode str to src args*/
    memset(hrt->file_name,'\0',hrt->file_name_len);
    memcpy(hrt->file_name,m_dest_code->buf,m_dest_code->len);

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;
    return true;

}

/*
*decode pars
*/
bool SvrClient::decode_pars(http_request_header * hrt,user_token * token)
{
    if(hrt == NULL || token == NULL)
        return false;

    bool ret =  false;
    /*get pars from file name*/
    if(hrt->pars_len == 0 && hrt->file_name_len > 64)
    {
        /*first,get pars*/
        char * ch_str = NULL;
        ch_str = strstr(hrt->file_name + 1,"/");
        if(ch_str != NULL)
        {
            hrt->pars_len = (size_t)(ch_str - hrt->file_name) - 1;
            if(hrt->pars_len > 0)
            {
                 memcpy(hrt->pars,hrt->file_name + 1 ,hrt->pars_len);
            }
        }
    }

    /*check pars format*/
    if(hrt->pars_len == 0)
    {
         return false;
    }

    /*replace struct char to base64 char*/
    unsigned int index = 0;
    while(index < hrt->pars_len)
    {
        if((*(hrt->pars+index)) == '-')
                (*(hrt->pars+index)) = '=';
        if((*(hrt->pars+index)) == '^')
                (*(hrt->pars+index)) = '/';
        if((*(hrt->pars+index)) == '~')
                       (*(hrt->pars+index)) = '/';
        /*next char*/
        index++;
    }
    /*now begin base64 decode*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*copy pars*/
    memcpy(m_src_code->buf,hrt->pars,hrt->pars_len);
    m_src_code->len = hrt->pars_len;
    m_dest_code->len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);

    /*get file name*/
    char * ch_str = NULL;
    ch_str = strstr((char *)m_dest_code->buf,"&file=");
    if(ch_str != NULL)
    {
        hrt->file_name_len =  m_dest_code->len - ((ubyte *)ch_str - m_dest_code->buf + 6);

        memset(hrt->file_name,'\0',MAX_REQ_PATH_LEN);
        memcpy(hrt->file_name,ch_str + 6,hrt->file_name_len);

        /*update pars*/
        m_dest_code->len -= 6 + hrt->file_name_len;
    }

    /*get session id*/
    ch_str = strstr((char *)m_dest_code->buf,"SessionID=");
    if(ch_str != NULL)
    {
        char * ch_end = NULL;
        ch_end =  strstr(ch_str,"&");
        if(ch_end != NULL)
        {
            size_t slen = ch_end - ch_str - 10;
            if(slen > 0  && slen < 64)
            {
                memcpy(token->key,ch_str + 10,slen);
                ret = true;
            }
        }
    }


    /*copy pars*/
    memset(hrt->pars,'\0',hrt->pars_len);
    memcpy(hrt->pars,m_dest_code->buf,m_dest_code->len);

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    /*return*/
    return ret;
}

/*
*decode administrator key
*/
bool SvrClient::decode_private_key(http_request_header * hrt)
{
    if(hrt == NULL)
          return false;

    if(hrt->privat_len == 0)
          return false;

    bool ret =  false;
    /*decode key*/
    op_buf * m_src_code = NULL, * m_dest_code = NULL;
    this->alloc_op_buf(&m_src_code);
    this->alloc_op_buf(&m_dest_code);
    if(m_src_code == NULL || m_dest_code == NULL)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*replace struct char to base64 char*/
    unsigned int index = 0;
    while(index < hrt->privat_len)
    {
        if((*(hrt->privat+index)) == '-')
                (*(hrt->privat+index)) = '=';

        if((*(hrt->privat+index)) == '^')
                (*(hrt->privat+index)) = '/';

        if((*(hrt->privat+index)) == '~')
                (*(hrt->privat+index)) = '/';
        /*next char*/
        index++;
    }

    /*copy pars and base64 decode*/
    memcpy(m_src_code->buf,hrt->privat,hrt->privat_len);
    m_src_code->len = hrt->privat_len;
    m_dest_code->len =  utils::decode_base64(m_dest_code->buf,op_buf_len,m_src_code->buf,m_src_code->len);
    if(m_dest_code->len == 0)
    {
        this->free_op_buf(m_src_code);
        this->free_op_buf(m_dest_code);
        m_src_code = NULL;
        m_dest_code = NULL;
        return false;
    }

    /*3des decoder*/
    memset(m_src_code->buf,NULL,op_buf_len);
    m_src_code->len = des3_decrypt_default(m_dest_code->buf,m_dest_code->len,m_src_code->buf,op_buf_len);
    if(m_src_code->len == 0)
    {
	   this->free_op_buf(m_src_code);
	   this->free_op_buf(m_dest_code);
	   m_src_code = NULL;
	   m_dest_code = NULL;
	   return false;
    }
    /*str trim*/
    int count = 0;
    for(size_t i = m_src_code->len -1 ;i > 0 ; i--)
    {
        int code = m_src_code->buf[i];
        if(code <= 32 || code >= 127)
        {
            count ++;
        }
        else
        {
            break;
        }
    }
    m_src_code->len -= count;
    /*copy key*/
    if(m_src_code->len > 0)
    {
        memset(hrt->privat,'\0',hrt->privat_len);
        memcpy(hrt->privat,m_src_code->buf,m_src_code->len);
        hrt->privat_len = m_src_code->len;
        ret = true;
    }

    /*free buf*/
    this->free_op_buf(m_src_code);
    this->free_op_buf(m_dest_code);
    m_src_code = NULL;
    m_dest_code = NULL;

    /*return*/
    return ret;
}

/*
*encode key
*/
bool SvrClient::encode_private_key(char * data, size_t data_len,size_t max_buf_len)
{
	if(data == NULL)
		return false;

	if(data_len == 0)
		return false;

	if(max_buf_len < data_len)
		return false;

	bool ret = false;
	/*encode key*/
	op_buf * m_src_code = NULL, * m_dest_code = NULL;
	this->alloc_op_buf(&m_src_code);
	this->alloc_op_buf(&m_dest_code);
	if(m_src_code == NULL || m_dest_code == NULL)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}

	/*init*/
	memcpy(m_src_code->buf,data,data_len);
	m_src_code->len = data_len;

	/*first 3des*/
	m_dest_code->len = des3_encrypt_default(m_src_code->buf,m_src_code->len,m_dest_code->buf,op_buf_len);
	if(m_dest_code->len == 0)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}

	/*second base64*/
	memset(m_src_code->buf,NULL,op_buf_len);
	m_src_code->len = 0;
	m_src_code->len = utils::encode_base64(m_src_code->buf,op_buf_len,m_dest_code->buf,m_dest_code->len);
	if(m_src_code->len == 0)
	{
		this->free_op_buf(m_src_code);
		this->free_op_buf(m_dest_code);
		m_src_code = NULL;
		m_dest_code = NULL;
		return false;
	}
	else
	{
		/*replace struct char to base64 char*/
		size_t index = 0;
		while(index < m_src_code->len)
		{
			if((*(m_src_code->buf+index)) == '=')
				(*(m_src_code->buf+index)) = '-';

			if((*(m_src_code->buf+index)) == '/')
				(*(m_src_code->buf+index)) = '~';

			/*next char*/
			index++;
		}

		/*copy*/
		memset(data,'\0',max_buf_len);
		memcpy(data,m_src_code->buf,m_src_code->len);
	}

	/*free buf*/
	this->free_op_buf(m_src_code);
	this->free_op_buf(m_dest_code);
	m_src_code = NULL;
	m_dest_code = NULL;

	/*return*/
	return ret;
}

/*
*check administrator operation cmd args
*/
Client_Type SvrClient::administrator_op_cmd(http_request_header *hrt)
{
    if(hrt == NULL)
        return INVALID_TYPE;

    Client_Type ret_type = HTTP_ADMIN_CLIENT;
    if(decode_private_key(hrt))
    {
        /*get closefile cmd line*/
        if(hrt->privat_len > 6 && memcmp(hrt->privat,"clear:", 6) == 0)
        {
              //this->clear_client_connect_by_request_content(hrt->privat + 6);
        }
        else if(hrt->privat_len > 6 && memcmp(hrt->privat,"close:", 6) == 0)
        {
              //this->force_client_list_offline(hrt->privat + 6);
        }
        else if(hrt->privat_len > 6 && memcmp(hrt->privat,"login:", 6) == 0)
        {
             // ret_type =  SVR_ADMIN;
        }
    }
    else
    {
        ret_type =  HTTP_ADMIN_CLIENT;
    }

    return ret_type;
}

/**
 *add cdn auth
 */
void SvrClient::add_cdn_auth(http_request_header * hrt,user_token * token,bool authflag)
{
	 if(hrt == NULL || token == NULL)
	 {
	     return ;
	 }
	 /**
	  * decode private
	  */
	 if(!decode_private_key(hrt))
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"decode private data error:%s",hrt->privat);
		 /*return*/
		 token->type = INVALID_TYPE;
		 return ;
	 }
	 /**
	  *check privt and pars is match
	  */
	 if(hrt->pars_len != hrt->privat_len
			 ||memcmp(hrt->pars,hrt->privat,hrt->privat_len) != 0)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"request private data and pars not match,privat:%s,pars:%s",hrt->privat,hrt->pars);
		 /*return*/
		 token->type = INVALID_TYPE;
		 return ;
	 }

	 /*
	  *decode url pars
	  *dis-auth.apsx?pars=xxxcfalsfslkf-&connid=1234&totalbytes=123456&userip=119.97.146.163&randcode=12134
	  */
	 if(hrt->pars_len == 0 || !this->decode_pars(hrt,token))
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"decode url pars error:%s",hrt->path);
		 /*return*/
		 token->type = INVALID_TYPE;
		 return ;
	 }

	 /**
	  * auth log
	  */
	 this->pSvrlog->log_fmt(LOG_INFO,"server auth,url:%s,privt :%s!\r\n",hrt->path,hrt->privat);

	 /**
	  * db operation
	  */
	 connection_table_row * pRow = NULL;
	 this->pDbutils->alloc_connection_row_buf(&pRow);
	 if(pRow == NULL)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"[%s]add_cdn_auth,alloc_vodconnection_buf error:%s",token->key,hrt->path);
		 /*return*/
		 token->type = INVALID_TYPE;
		 return ;
	 }

	 /*get request  arg buf allocs*/
	 op_buf * m_src_code = NULL, * m_dest_code = NULL;
	 this->alloc_op_buf(&m_src_code);
	 this->alloc_op_buf(&m_dest_code);
	 if(m_src_code == NULL || m_dest_code == NULL)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"[%s]add_cdn_auth,alloc_op_buf error:%s",token->key,hrt->path);
		 this->free_op_buf(m_src_code);
		 this->free_op_buf(m_dest_code);
		 m_src_code = NULL;
		 m_dest_code = NULL;
		 return;
	 }

	 /*
	  * sqlstr buf
	  * */
	 char sqlstr[4096];

	 /*check auth data*/
	 if(authflag)
	 {
		 /**
		  *add to data base
		  */
		 if(this->pDbutils->connectodb() == 200)
		 {
			memset(sqlstr,'\0',sizeof(sqlstr));
			sprintf(sqlstr, "select *  from connections where SessionId = '%s' limit 0,1",token->key);
			this->pDbutils->querryconnection(sqlstr,pRow);
			if(pRow->fit_flag == 0)
			{
				 /**
				  * fetch url pars [userip]
				  */
				 memset(m_src_code->buf,'\0',op_buf_len);
				 m_src_code->len = 0;
				 m_src_code->len = http::get_url_pars_value(hrt,"userip=",(char *)m_src_code->buf,op_buf_len);

				 /**
				  * fetch url pars [connid]
				  */
				 memset(m_dest_code->buf,'\0',op_buf_len);
				 m_dest_code->len = 0;
				 m_dest_code->len = http::get_url_pars_value(hrt,"connid=",(char *)m_dest_code->buf,op_buf_len);
				 int connid = atoi((char *)m_dest_code->buf);

				 /*insert to table*/
				 memset(sqlstr,'\0',sizeof(sqlstr));
				 sprintf(sqlstr, "INSERT INTO connections (Node_Id,Conn_Id,CleintIP,SessionId,File_Name,Url,SessionBeginTime)  "
						"VALUES (%d,%d,'%s','%s','%s','%s',%ld)",
						this->pSvrconfig->Svr_Id,
						connid,
						(char *)m_src_code->buf,
						token->key,
						hrt->file_name,
						hrt->path,
						(long)time(NULL));

				 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
				 {
					 this->pSvrlog->log_fmt(LOG_WARN,"[%s]add_cdn_auth(), insert to db error:%s",token->key,hrt->path);
				 }
			}
		 }
	 }
	 else
	 {
		 if(this->pDbutils->connectodb() == 200)
		 {
			 memset(sqlstr,'\0',sizeof(sqlstr));
			 sprintf(sqlstr, "select *  from connections where SessionId = '%s' and status < 3 limit 0,1",token->key);
			 this->pDbutils->querryconnection(sqlstr,pRow);
			 if(pRow->fit_flag == 1)
			 {
				 /**
				  * fetch url pars [totalbytes]
				  */
				 memset(m_src_code->buf,'\0',op_buf_len);
				 m_src_code->len = 0;
				 m_src_code->len = http::get_url_pars_value(hrt,"totalbytes=",(char *)m_src_code->buf,op_buf_len);
				 unsigned long long totalbytes =  strtoull((char *)m_src_code->buf,NULL,10);
				 pRow->SessionEndTime = (long)time(NULL) ;
				 int totalseconds = (int)(pRow->SessionEndTime - pRow->SessionBeginTime);

				 /**
				  *update data base
				  */
				 memset(sqlstr,'\0',sizeof(sqlstr));
				 sprintf(sqlstr, "UPDATE connections set Total_KB = %llu, Total_Secs = %d, SessionEndTime=%ld, status = 3 where SessionId = '%s'",
						totalbytes,
						totalseconds,
						pRow->SessionEndTime,
						token->key);

				 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
				 {
					 this->pSvrlog->log_fmt(LOG_WARN,"[%s]add_cdn_auth(), update to db error:%s",token->key,hrt->path);
				 }

			 }
		 }
	 }

	 /*free table row buf*/
	this->pDbutils->free_connection_row_buf(pRow);
	pRow = NULL;

	/*free buf*/
	this->free_op_buf(m_src_code);
	this->free_op_buf(m_dest_code);
	m_src_code = NULL;
	m_dest_code = NULL;

	token->type = CDN_AUTH_CLIENT;

}

/**
 * set request content offset
 */
void SvrClient::set_request_content_offset(http_request_header * hrt,user_token * token)
{
	/*request rang*/
	if(hrt->content_offset >= token->hFile_size)
	{
		hrt->content_offset = (token->hFile_size - 1);
	}

	if(hrt->content_end  >= token->hFile_size)
	{
		hrt->content_end = (token->hFile_size -1);
	}

	if(hrt->content_offset > 0 || hrt->content_end > 0)
	{
		token->hFile_offset = hrt->content_offset;

		if(hrt->content_end < hrt->content_offset)
		{
			 hrt->content_end = (token->hFile_size - 1);
		}

		token->trans_size = (hrt->content_end - hrt->content_offset + 1);
	}
	else if(hrt->is_have_rang) /*some request ,rang:bytes=0-*/
	{
		token->trans_size = token->hFile_size;
	}

}

/*
*get request type
*/
Client_Type SvrClient::anylsis_client_type(char * buf,size_t buf_len,user_token * token)
{
    if(buf == NULL || buf_len == 0 ||  token == NULL)
       return INVALID_TYPE;

    int ret = FAILURE;
    Client_Type ret_type = INVALID_TYPE;
    http_request_header *hrt = NULL;
    this->alloc_request_header(&hrt);
    int parsecode = 0;
    ret = http::parse_request_header(hrt,buf,buf_len,parsecode);
    if(ret != SUCCESS)
    {
    	if(parsecode == 1 && hrt->method != UNKNOW)
    	{
    		this->free_request_header(hrt);
    		return ON_RECV_TYPE;
    	}

        this->pSvrlog->log_fmt(LOG_ERR,"Parse_Request_Header_Error:%s\r\n",buf);
        this->free_request_header(hrt);
        return INVALID_TYPE;
    }

    /*
     * check is receive completed
     */
    if(hrt->header_len == 0)
    {
       this->free_request_header(hrt);
       return ON_RECV_TYPE;
    }

    /*
    *check file name
    */
    if(hrt->mime == NONE && hrt->file_name_len > 0 &&  hrt->pars_len >0)
    {
        if(decode_file_name(hrt,token))
        {
             hrt->mime = http::anlysis_mime_type(hrt);
        }
    }

    /*
    *check request type
    */
    if(hrt->mime == XML)
	{
		token->type = HTTP_BROWSE;
		ret_type =  HTTP_BROWSE;
	}
    else if(hrt->mime == INFO)
    {
        ret_type = administrator_op_cmd(hrt);
        token->type = ret_type;
    }
    else if(hrt->mime == ASPNET)
    {
    	/*
		 * check is player client
		 */
		if(memcmp(hrt->file_name,"/auth.aspx",10) == 0)
		{
			/*add auth client*/
			add_cdn_auth(hrt,token);
		}
		else if(memcmp(hrt->file_name,"/disauth.aspx",13) == 0)
		{
			/*add disauth client*/
			add_cdn_auth(hrt,token,false);
		}
		else if(memcmp(hrt->file_name,"/heartbeat.aspx",15) == 0)
		{
			if(!decode_private_key(hrt))
			{
				 this->pSvrlog->log_fmt(LOG_ERR,"decode private data error:%s",hrt->privat);
				 token->type = INVALID_TYPE;
			}
			else
			{
				/*xMedia server is keepalive*/
				/**xLiveServer / xMediaServer**/
				/**heartbeat.aspx?type=xLiveServer&session_count=%d&connection_count=%d**/
				token->type = HTTP_BROWSE;
				/*add your code here*/
				this->pSvrlog->log_fmt(LOG_INFO,"server heartbeat url:%s!\r\n",hrt->path);
			}
		}
        ret_type =  (Client_Type)token->type;
    }
    else
    {
    	/*
    	 * check reqeust limt
    	 **/


    	/**
    	 * get file name md5 hash key
    	 */
    	if(hrt->file_name_len > 0)
    	{
    		uint8_t outbuf[GUID_LEN];
    		memset(outbuf,0,GUID_LEN);
    		md5_sum(outbuf,(uint8_t *)hrt->file_name,hrt->file_name_len);
    		utils::hexa(token->key,outbuf,16);
    	}

        /*
         * set mime,and request rang
         **/
        token->fmt = hrt->mime;

        /*support url seek*/
        if(hrt->seek_offset > 0 && hrt->content_offset == 0)
        {
            hrt->content_offset = hrt->seek_offset;
        }

        /*
         * open file handle
         **/
        if(open_request_file(hrt,token))
        {
        	set_request_content_offset(hrt,token);
        }
        else
        {
            /*log:*/
            this->pSvrlog->log_fmt(LOG_ERR,"[%s]Open File Error,FileName:%s\r\n",token->key,hrt->file_name);
            this->free_request_header(hrt);
            return INVALID_TYPE;
        }

        /*
         * CDN Delivery client request
         */
        token->type = CDN_DELIVERY_CLIENT;
        ret_type =  CDN_DELIVERY_CLIENT;
    }

    /*must free http request vars*/
    this->free_request_header(hrt);
    return ret_type;
}

/**
* check auth result
*/
AUTH_STATUS SvrClient::check_auth_result(char * key)
{
	if(key == NULL || strlen(key) == 0)
		return AUTH_FAILURE;

	 /**
	  * db operation
	  */
	 connection_table_row * pRow = NULL;
	 this->pDbutils->alloc_connection_row_buf(&pRow);
	 if(pRow == NULL)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"[%w]check_auth_result alloc_vodconnection_buf error:%s",key);
		 return AUTH_SUCCESS;
	 }

	 /*
	  * sqlstr buf
	  * */
	 AUTH_STATUS ret = AUTH_SUCCESS;
	 if(this->pDbutils->connectodb() == 200)
	 {
		 char sqlstr[4096];
		 memset(sqlstr,'\0',sizeof(sqlstr));
		 sprintf(sqlstr, "select *  from connections where SessionId = '%s' limit 0,1",key);
		 this->pDbutils->querryconnection(sqlstr,pRow);
		 if(pRow->fit_flag == 1)
		 {
			 if(pRow->status == 0 || pRow->status == 1)
			 {
				 ret = AUTH_WAIT;
			 }
			 else
			 {
				 if(pRow->flag == 1)
				 {
					 ret = AUTH_SUCCESS;
				 }
				 else
				 {
					 ret = AUTH_FAILURE;
				 }
			 }
		 }
	 }

	 /*free table row buf*/
	 this->pDbutils->free_connection_row_buf(pRow);
	 pRow = NULL;

	 return ret;
}

/*
*get auth task
*/
user_token * SvrClient::get_next_session_auth_task(void)
{
    user_token * newtoken = NULL;
    handle_lock.Lock();
    {
        if(handle_auth_list.size() > 0)
        {
            newtoken = handle_auth_list.front();
            handle_auth_list.pop();
        }

        handle_lock.Unlock();
    }

    return newtoken;
}

/*
*struct_auth_request_data
*/
uint32_t SvrClient::struct_auth_request_data(char * buf,size_t buf_len,const char * key)
{
     if(buf == NULL || buf_len == 0 || key == NULL)
            return 0;

     /**
	  * db operation
	  */
     connection_table_row * pRow = NULL;
	 this->pDbutils->alloc_connection_row_buf(&pRow);
	 if(pRow == NULL)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"[%s]struct_auth_request_data alloc_vodconnection_buf error",key);
		 return 0;
	 }

	 /*
	  * sqlstr buf
	  * */
	 if(this->pDbutils->connectodb() == 200)
	 {
		 char sqlstr[4096];
		 memset(sqlstr,'\0',sizeof(sqlstr));
		 sprintf(sqlstr, "select *  from connections where SessionId = '%s' limit 0,1",key);
		 this->pDbutils->querryconnection(sqlstr,pRow);
		 if(pRow->fit_flag == 1)
		 {
			 if(pRow->status == 1)
			 {
				 sprintf(buf,"mgv-4\r\nauth-url:%s\r\nnode-id:%d\r\nconn-id:%d\r\nclient-ip:%s\r\nuser-agent:mgv\r\n\r\n",
						 pRow->Url,pSvrconfig->Svr_Id,pRow->Conn_Id,pRow->CleintIP);
			 }
			 else if(pRow->status == 4)
			 {
				 long size = (long)(pRow->Total_KB / 1024);
				 sprintf(buf,"mgv-5\r\nauth-url:%s\r\nnode-id:%d\r\nconn-id:%d\r\nclient-ip:%s\r\ntotal-seconds:%d\r\ntotal-size:%ld\r\nuser-agent:mgv\r\ncdn-ssid:%s\r\n\r\n",
					pRow->Url,
					pSvrconfig->Svr_Id,
					pRow->Conn_Id,
					pRow->CleintIP,
					pRow->Total_Secs,
					size,
					pRow->SessionId);
			 }
		 }
	 }

	 /*free table row buf*/
	 this->pDbutils->free_connection_row_buf(pRow);
	 pRow = NULL;

	/**
	 * return
	 */
    return (uint32_t)strlen(buf);
}

/*
*anylsis_auth_result
*/
AUTH_STATUS SvrClient::anylsis_auth_result(char * buf,size_t buf_len,const char * key)
{
     if(buf == NULL || key == NULL)
       return AUTH_FAILURE;

   	 /**
   	 * anylsis_auth_result
   	 */
   	 AUTH_STATUS authResult = AUTH_SUCCESS;
   	 int auth_result = 1;
   	 /**
   	 * qurre db
   	 */
     connection_table_row * pRow = NULL;
   	 this->pDbutils->alloc_connection_row_buf(&pRow);
   	 if(pRow == NULL)
   	 {
   		 this->pSvrlog->log_fmt(LOG_ERR,"[%s]anylsis_auth_result alloc_vodconnection_buf error",key);
   		 return authResult;
   	 }
   	 if(this->pDbutils->connectodb() == 200)
	 {
		 char sqlstr[4096];
		 memset(sqlstr,'\0',sizeof(sqlstr));
		 sprintf(sqlstr, "select *  from connections where SessionId = '%s' limit 0,1",key);
		 this->pDbutils->querryconnection(sqlstr,pRow);
		 if(pRow->fit_flag == 1)
		 {
			 if(pRow->status == 1)
			 {
				 memset(sqlstr,'\0',sizeof(sqlstr));
				 sprintf(sqlstr, "UPDATE connections set status = 2, flag = %d where id = %d",auth_result,pRow->id);
				 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
				 {
					 this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 2, update to db error:%s",pRow->SessionId,pRow->Url);
				 }
			 }
			 else if(pRow->status == 4)
			 {
				 memset(sqlstr,'\0',sizeof(sqlstr));
				 sprintf(sqlstr, "UPDATE connections set status = 5 where id = %d",pRow->id);
				 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
				 {
					 this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 5, update to db error:%s",pRow->SessionId,pRow->Url);
				 }
			 }
		 }
	 }

   	 /*free table row buf*/
	 this->pDbutils->free_connection_row_buf(pRow);
	 pRow = NULL;

     /*return result*/
     return authResult;
}

/*
 * run
 */
void SvrClient::run(void)
{
	 /*querry sql db get auth task*/
	connection_table_row * pRow = NULL;
	 this->pDbutils->alloc_connection_row_buf(&pRow);
	 if(pRow == NULL)
	 {
		 this->pSvrlog->log_fmt(LOG_ERR,"run, alloc_vodconnection_buf error");
		 return;
	 }
	 /*
	  * sqlstr buf
	  * */
	 if(this->pDbutils->connectodb() == 200)
	 {
		 char sqlstr[4096];
		 for(int i = 0 ;i < 100; i++)
		 {
			 /**
			  * querryvodconnection status :0 and 3
			  */
			 memset(sqlstr,'\0',sizeof(sqlstr));
			 sprintf(sqlstr, "select *  from connections where status = 0 or status = 3  limit 0,1");
			 this->pDbutils->reset_connection_row_buf(pRow);
			 this->pDbutils->querryconnection(sqlstr,pRow);
			 if(pRow->fit_flag == 1)
			 {
				 if(pRow->status == 0)
				 {
					 /**
					  * local auth
					  */
					 memset(sqlstr,'\0',sizeof(sqlstr));
					 sprintf(sqlstr, "UPDATE connections set status = 2, flag = 1 where id = %d",pRow->id);
					 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
					 {
						 this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 2, update to db error:%s",pRow->SessionId,pRow->Url);
					 }
					 /* net auth*/
					 //memset(sqlstr,'\0',sizeof(sqlstr));
					 //sprintf(sqlstr, "UPDATE connections set status = 1 where id = %d",pRow->id);
					 //if(this->pDbutils->execnosql(sqlstr) != 200)
					 //{
						 //this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 1, update to db error:%s",pRow->SessionId,pRow->Url);
					 //}
					 /*user_token * newtoken = NULL;
					 this->alloc(&newtoken);
					 newtoken->id = token->id;
					 memset(newtoken->key,'\0',sizeof(newtoken->key));
					 strcpy(newtoken->key,token->key);
					 newtoken->type = CDN_AUTH_SERVER;
					 handle_lock.Lock();
					 {
						 handle_auth_list.push(newtoken);

						 handle_lock.Unlock();
					 }*/

				 }
				 else if(pRow->status == 3)
				 {
					 /**
					  * local auth
					  */
					 memset(sqlstr,'\0',sizeof(sqlstr));
					 sprintf(sqlstr, "UPDATE connections set status = 5 where id = %d",pRow->id);
					 if(this->pDbutils->execconnectionnosql(sqlstr) != 200)
					 {
						 this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 5, update to db error:%s",pRow->SessionId,pRow->Url);
					 }

					 /* net auth*/
					 //memset(sqlstr,'\0',sizeof(sqlstr));
					 //sprintf(sqlstr, "UPDATE connections set status = 4 where id = %d",pRow->id);
					 //if(this->pDbutils->execnosql(sqlstr) != 200)
					 //{
						 //this->pSvrlog->log_fmt(LOG_WARN,"[%s]update auth status to 4, update to db error:%s",pRow->SessionId,pRow->Url);
					 //}
					 /*user_token * newtoken = NULL;
					 this->alloc(&newtoken);
					 newtoken->id = token->id;
					 memset(newtoken->key,'\0',sizeof(newtoken->key));
					 strcpy(newtoken->key,token->key);
					 newtoken->type = CDN_AUTH_SERVER;
					 handle_lock.Lock();
					 {
						 handle_auth_list.push(newtoken);

						 handle_lock.Unlock();
					 }*/
				 }
			 }
			 else
			 {
				 break;
			 }
		 }

		 /**
		  * clean history session
		  */
		 if(this->client_time_tick > 10)
		 {
			 /* out of config time*/
			 long curtime = (long)time(NULL);
			 memset(sqlstr,'\0',sizeof(sqlstr));
			 sprintf(sqlstr,"delete from connections where SessionBeginTime < %ld",curtime - this->pSvrconfig->clearOutTime);
			 this->pDbutils->execconnectionnosql(sqlstr);

			 /*handle exception recoder,auth not complete out of 120 seconds*/
			 memset(sqlstr,'\0',sizeof(sqlstr));
			 sprintf(sqlstr, "UPDATE connections set status = 2, flag = 1 where status < 2 and SessionBeginTime < %ld",curtime - 120);
			 this->pDbutils->execconnectionnosql(sqlstr);

			 /*handle exception recoder,disauth not complete out of 14400 seconds*/
			 memset(sqlstr,'\0',sizeof(sqlstr));
			 sprintf(sqlstr, "UPDATE connections set status = 3, SessionEndTime = %ld where status < 3 and SessionBeginTime < %ld",curtime , curtime - 14400);
			 this->pDbutils->execconnectionnosql(sqlstr);

			 /*reset time tick*/
			 this->client_time_tick = 0;
		 }
	 }

	 /*free table row buf*/
	 this->pDbutils->free_connection_row_buf(pRow);
	 pRow = NULL;

	 /*----run end---*/
	 this->client_time_tick ++;
}
